/*  Copyright (c) 2012 William Rogers and James Boud

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

using System;
using SlimDX;
using SlimDX.Direct3D11;
//using Microsoft.Xna.Framework.Graphics;

namespace JBBRXG11
{
    public class GraphicsDevice : IDisposable
    {
        const int max_stream_out_buffers = 8;
        Device dx_device;
        DeviceContext dx_dev_context;
        int width, height;             // size of the screen or window
        int targetwidth, targetheight; // size of the current rendertarget (could be screen or window)
        RenderState renderstate;
        SlimDX.DXGI.SwapChain swap_chain;
        SlimDX.Direct3D11.Texture2D z_buffer;
        RenderTargetView backbuffer_render_target_view;
        RenderTargetView[] current_render_targets, twotarget, threetarget;  // could have more - nyi
        StreamOutputBufferBinding[] current_stream_output_buffers, onesobuffer, twosobuffer, threesobuffer;  // not sure how many are possible
        DepthStencilView depth_stencil_view, current_depth_stencil_view;
        Viewport screen_viewport;
        Microsoft.Xna.Framework.Graphics.VertexBufferBinding[] vbuffs = null;
        VertexBuffer vbuff;
        //TODO: Check if we should remove VertexDeclaration. (We use it a lot but we have VertexBuffer);
        VertexDeclaration vdecl;
        VertexStreamCollection vertexstreamcollection;
        IndexBuffer indices;
        // Cache the current preferred pixel shader passes for sprite batch processing
        // This allows us to override the pixel shader in XNA code 
        JBBRXG11.EffectPass spritebatch_effectpass;

        internal Device DX_Device { get { return dx_device; } }
        internal DeviceContext DX_Device_Context { get { return dx_dev_context; } }
        internal int TargetWidth { get { return targetwidth; } }
        internal int TargetHeight { get { return targetheight; } }
        /// <summary>
        ///     Gets or sets a viewport identifying the portion of the render target to receive
        ///     draw calls. Reference page contains code sample.
        /// </summary>
        public JBBRXG11.Viewport Viewport
        {
            get { return new JBBRXG11.Viewport(0, 0, targetwidth, targetheight); }
            set { throw new Exception("GraphicsDevice.Viewport set not yet implemented"); }
        }
        public RenderState RenderState { get { return renderstate; } }

        //public void SetVertexBuffer(Microsoft.Xna.Framework.Graphics.VertexBuffer vertexBuffer)
        //{
        //    throw new Exception("Not Yet Implemented");
        //    if (vbuffs == null)
        //    {

        //    }
        //    else
        //    {
        //        //TODO: (This was already commented out. Why?) Microsoft.Xna.Framework.Graphics.VertexBufferBinding z = new Microsoft.Xna.Framework.Graphics.VertexBufferBinding(vertexBuffer);
        //    }
        //}

        /// <summary>
        /// Sets or binds a vertex buffer to the device.
        /// </summary>
        /// <param name="vertexBuffer">A vertex buffer.</param>
        public void SetVertexBuffer(VertexBuffer vertexBuffer)
        {
            vbuff = vertexBuffer;
            dx_dev_context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vbuff.DX_Buffer, vbuff.StrideSize, 0));
        }


        public void SetVertexBuffer(VertexBuffer vertexBuffer, int vertexOffSet)
        {

        }
        //public void SetVertexBuffer(params VertexBufferBinding[] vertexBuffers)
        //{
        //    throw new Exception("Not Yet Implemented");

        //}
        public Microsoft.Xna.Framework.Graphics.VertexBufferBinding[] GetVertexBuffers()
        {
            throw new Exception("Not Yet Implemented");
            return null;
            return vbuffs;
        }

        internal JBBRXG11.EffectPass SpriteBatchEffectPass
        {
            get { return spritebatch_effectpass; }
            set { spritebatch_effectpass = value; }
        }

        internal GraphicsDevice(bool iswin, int prefwidth, int prefheight,
                                Microsoft.Xna.Framework.Graphics.SurfaceFormat prefbackbufferformat,
                                Microsoft.Xna.Framework.Graphics.DepthFormat prefdepthstencilformat,
                                GameWindow gamewin)
        {
            // Create the swap chain
            SlimDX.DXGI.SwapChainDescription swapchaindesc;
            SlimDX.DXGI.ModeDescription modedesc;
            SlimDX.DXGI.SampleDescription sampledesc;
            Result res;
            swapchaindesc = new SlimDX.DXGI.SwapChainDescription();
            swapchaindesc.BufferCount = 1;
            swapchaindesc.Flags = SlimDX.DXGI.SwapChainFlags.None;
            swapchaindesc.IsWindowed = iswin;
            modedesc = new SlimDX.DXGI.ModeDescription();
            modedesc.Format = EnumConversions.convert(prefbackbufferformat);
            modedesc.Width = (iswin ? prefwidth : 0);
            modedesc.Height = (iswin ? prefheight : 0);
            modedesc.RefreshRate = new Rational(60, 1);
            modedesc.Scaling = SlimDX.DXGI.DisplayModeScaling.Unspecified;
            modedesc.ScanlineOrdering = SlimDX.DXGI.DisplayModeScanlineOrdering.Unspecified;
            swapchaindesc.ModeDescription = modedesc;
            swapchaindesc.OutputHandle = gamewin.Handle;
            sampledesc = new SlimDX.DXGI.SampleDescription();
            sampledesc.Count = 1;
            sampledesc.Quality = 0;
            swapchaindesc.SampleDescription = sampledesc;
            swapchaindesc.SwapEffect = SlimDX.DXGI.SwapEffect.Sequential;
            swapchaindesc.Usage = SlimDX.DXGI.Usage.RenderTargetOutput;

            res = Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.None, swapchaindesc, out dx_device, out swap_chain);
            if (res.IsFailure)
            {
                System.Windows.Forms.MessageBox.Show("Couldn't create DX11 device");
                return;
            }

            // Find width and height for the device created, in the case that it turned out to be full screen
            bool didfullscreen;
            SlimDX.DXGI.Output screendescription;
            swap_chain.GetFullScreenState(out didfullscreen, out screendescription);
            if (didfullscreen)
            {
                width = screendescription.Description.DesktopBounds.Width;
                height = screendescription.Description.DesktopBounds.Height;
                gamewin.SetToFullScreen = true;
                gamewin.ScreenWidth = width;
                gamewin.ScreenHeight = height;
            }
            else
            {
                width = prefwidth;
                height = prefheight;
            }

            // Allocate the depth buffer
            Texture2DDescription depthbufferdesc;
            depthbufferdesc = new Texture2DDescription();
            depthbufferdesc.Width = width;
            depthbufferdesc.Height = height;
            depthbufferdesc.MipLevels = 1;
            depthbufferdesc.ArraySize = 1;
            depthbufferdesc.Format = EnumConversions.convert(prefdepthstencilformat);
            depthbufferdesc.SampleDescription = new SlimDX.DXGI.SampleDescription(1, 0);
            depthbufferdesc.Usage = ResourceUsage.Default;
            depthbufferdesc.BindFlags = BindFlags.DepthStencil;
            depthbufferdesc.CpuAccessFlags = CpuAccessFlags.None;
            depthbufferdesc.OptionFlags = ResourceOptionFlags.None;

            z_buffer = new SlimDX.Direct3D11.Texture2D(dx_device, depthbufferdesc);
            DepthStencilViewDescription depthstencildesc;
            depthstencildesc = new DepthStencilViewDescription();
            depthstencildesc.Flags = DepthStencilViewFlags.None;
            depthstencildesc.Format = depthbufferdesc.Format;
            depthstencildesc.Dimension = DepthStencilViewDimension.Texture2D;
            depthstencildesc.MipSlice = 0;
            depth_stencil_view = new DepthStencilView(dx_device, z_buffer, depthstencildesc);

            // Create the render target view
            SlimDX.Direct3D11.Texture2D back_buffer
                = SlimDX.Direct3D11.Texture2D.FromSwapChain<SlimDX.Direct3D11.Texture2D>(swap_chain, 0);
            backbuffer_render_target_view = new RenderTargetView(dx_device, back_buffer);
            dx_dev_context = dx_device.ImmediateContext;
            //dx_device.ImmediateContext.OutputMerger.SetTargets(depth_stencil_view, backbuffer_render_target_view);
            current_depth_stencil_view = depth_stencil_view;
            dx_dev_context.OutputMerger.SetTargets(current_depth_stencil_view, backbuffer_render_target_view);
            back_buffer.Dispose();

            // Keep track of rendertarget assignments
            current_render_targets = new RenderTargetView[8];
            twotarget = new RenderTargetView[2];
            threetarget = new RenderTargetView[3];
            for (int t = 0; t < 8; t++) current_render_targets[t] = null;
            current_render_targets[0] = backbuffer_render_target_view;
            // Keep track of stream out buffer assignments
            current_stream_output_buffers = new StreamOutputBufferBinding[max_stream_out_buffers];
            onesobuffer = new StreamOutputBufferBinding[1];
            twosobuffer = new StreamOutputBufferBinding[2];
            threesobuffer = new StreamOutputBufferBinding[3];
            for (int s = 0; s < max_stream_out_buffers; s++) current_stream_output_buffers[s] = new StreamOutputBufferBinding(null, 0);
            // Set the viewport
            screen_viewport = new Viewport(0, 0, width, height);
            targetwidth = width; targetheight = height;
            dx_dev_context.Rasterizer.SetViewports(screen_viewport.DXViewport);
            vdecl = null;
            renderstate = new RenderState(this);
            vertexstreamcollection = new VertexStreamCollection(this);
            indices = null;
        }
        
        //
        // Summary:
        //     Gets or sets a vertex shader declaration.
        public VertexDeclaration VertexDeclaration
        {
            get
            {
                return vdecl;
            }
            set
            {
                vdecl = value;
                if (!vdecl.AwaitingUse)
                    dx_dev_context.InputAssembler.InputLayout = vdecl.VertexLayout;
            }
        }

        internal void CheckAndSetVertexLayout(EffectPass pass)
        {
            // TODO:  Temporary removal of vdecl check so that compute shader doesn't fail - needs fixing
            if (vdecl == null)
                return;
                //throw new Exception("Vertex declaration not set on graphics device");
            if (vdecl.AwaitingUse)
            {
                vdecl.CreateLayout(this, pass.DX_EffectPass.Description.Signature);
                dx_dev_context.InputAssembler.InputLayout = vdecl.VertexLayout;
            }
        }

        public VertexStreamCollection Vertices { get { return vertexstreamcollection; } }

        /// <summary>
        /// Gets or sets index data. The default value is null.
        /// </summary>
        public IndexBuffer Indices
        {
            get { return indices; }
            set
            {
                indices = value;
                if (value.IndexElementSize == Microsoft.Xna.Framework.Graphics.IndexElementSize.SixteenBits)
                    dx_dev_context.InputAssembler.SetIndexBuffer(value.DX_Buffer, SlimDX.DXGI.Format.R16_UInt, 0);
                else
                    dx_dev_context.InputAssembler.SetIndexBuffer(value.DX_Buffer, SlimDX.DXGI.Format.R32_UInt, 0);
            }
        }

        public void SetStreamOutBuffer(int streamOutBufferIndex, VertexBuffer buffer, int offset)
        {
            if (buffer != null && ((buffer.BufferUsage & BufferUsage.StreamOut) == 0))
                throw new Exception("Attempt to use vertex buffer created without stream-out flag as a stream-out buffer");
            current_stream_output_buffers[streamOutBufferIndex].Buffer = (buffer == null ? null : buffer.DX_Buffer);
            current_stream_output_buffers[streamOutBufferIndex].Offset = offset;
            int maxstream = -1;
            for (int s = 0; s < max_stream_out_buffers; s++)
                if (current_stream_output_buffers[s].Buffer != null)
                    maxstream = s;
                else
                    break;
            switch (maxstream)
            {
                case -1:
                    dx_dev_context.StreamOutput.SetTargets(null);
                    return;
                case 0:
                    onesobuffer[0] = current_stream_output_buffers[0];
                    dx_dev_context.StreamOutput.SetTargets(onesobuffer);
                    return;
                case 1:
                    twosobuffer[0] = current_stream_output_buffers[0];
                    twosobuffer[1] = current_stream_output_buffers[1];
                    dx_dev_context.StreamOutput.SetTargets(twosobuffer);
                    return;
                case 2:
                    threesobuffer[0] = current_stream_output_buffers[0];
                    threesobuffer[1] = current_stream_output_buffers[1];
                    threesobuffer[2] = current_stream_output_buffers[2];
                    dx_dev_context.StreamOutput.SetTargets(threesobuffer);
                    return;
            }
            throw new Exception("JBBRXG11 NYI Error: More than three stream output buffers not yet implemented");
        }

        void ConfigureRenderTargets()
        {
            int maxtarget = 0;
            for (int t = 1; t < 8; t++)
                if (current_render_targets[t] != null)
                    maxtarget = t;
            switch (maxtarget)
            {
                case 0:
                    dx_dev_context.OutputMerger.SetTargets(current_depth_stencil_view, current_render_targets[0]);
                    return;
                case 1:
                    twotarget[0] = current_render_targets[0];
                    twotarget[1] = current_render_targets[1];
                    dx_dev_context.OutputMerger.SetTargets(current_depth_stencil_view, twotarget);
                    return;
                case 2:
                    threetarget[0] = current_render_targets[0];
                    threetarget[1] = current_render_targets[1];
                    threetarget[2] = current_render_targets[2];
                    dx_dev_context.OutputMerger.SetTargets(current_depth_stencil_view, threetarget);
                    return;
            }
            throw new Exception("JBBRXG11 NYI Error: More than three render targets not yet implemented");
        }

        public void SetRenderTarget(int renderTargetIndex, RenderTarget2D renderTarget)
        {
            if (renderTargetIndex == 0 && renderTarget == null)
            {
                current_render_targets[renderTargetIndex] = backbuffer_render_target_view;
                current_depth_stencil_view = depth_stencil_view;
                targetwidth = width; targetheight = height;
                dx_dev_context.Rasterizer.SetViewports(screen_viewport.DXViewport);
                ConfigureRenderTargets();
            }
            else
            {
                current_render_targets[renderTargetIndex] = renderTarget.DX_TargetView;
                current_depth_stencil_view = renderTarget.DX_DepthStencilView;
                targetwidth = renderTarget.Width; targetheight = renderTarget.Height;
                dx_dev_context.Rasterizer.SetViewports(renderTarget.RenderViewport.DXViewport);
                ConfigureRenderTargets();
            }
        }

        /// <summary>
        /// Sets a new render target for this GraphicsDevice.
        /// </summary>
        /// <param name="renderTarget">A new render target for the device, or null to
        /// set the device render target to the back buffer of the device.</param>
        /// <param name="cubeMapFace">The cube map face type.</param>
        public void SetRenderTarget(RenderTargetCube renderTarget, Microsoft.Xna.Framework.Graphics.CubeMapFace cubeMapFace)
        {
            //throw new Exception("Not Yet Implemented");
            current_render_targets[0] = renderTarget.GetRenderTargetView(cubeMapFace);
            current_depth_stencil_view = renderTarget.DX_DepthStencilView;
            targetwidth = renderTarget.Size; targetheight = renderTarget.Size;
            dx_dev_context.Rasterizer.SetViewports(renderTarget.RenderViewport.DXViewport);
            ConfigureRenderTargets();  // TODO:  set the current depth stencil view
        }

        public void Clear(Microsoft.Xna.Framework.Color color)
        {
            dx_dev_context.ClearRenderTargetView(current_render_targets[0], new Color4(color.A / 256.0f, color.R / 256.0f, color.G / 256.0f, color.B / 256.0f));//(int)color.PackedValue));
            if (current_depth_stencil_view != null) dx_dev_context.ClearDepthStencilView(current_depth_stencil_view, DepthStencilClearFlags.Depth, 1.0f, 0);
        }

        public void Clear(Microsoft.Xna.Framework.Graphics.ClearOptions options,
                          Microsoft.Xna.Framework.Color color, float depth, int stencil)
        {
            if ((options & Microsoft.Xna.Framework.Graphics.ClearOptions.Target) != 0)
                dx_dev_context.ClearRenderTargetView(current_render_targets[0], new Color4(color.A / 256.0f, color.R / 256.0f, color.G / 256.0f, color.B / 256.0f));
            DepthStencilClearFlags flags = 0;
            if ((options & Microsoft.Xna.Framework.Graphics.ClearOptions.DepthBuffer) != 0)
                flags |= DepthStencilClearFlags.Depth;
            if ((options & Microsoft.Xna.Framework.Graphics.ClearOptions.Stencil) != 0)
                flags |= DepthStencilClearFlags.Stencil;
            dx_dev_context.ClearDepthStencilView(current_depth_stencil_view, flags, depth, (byte)stencil);
        }

        public void Clear(Microsoft.Xna.Framework.Graphics.ClearOptions options,
                          Microsoft.Xna.Framework.Vector4 color, float depth, int stencil)
        {
            if ((options & Microsoft.Xna.Framework.Graphics.ClearOptions.Target) != 0)
                dx_dev_context.ClearRenderTargetView(current_render_targets[0],
                                                new Color4(new Vector4(color.X, color.Y, color.Z, color.W)));
            DepthStencilClearFlags flags = 0;
            if ((options & Microsoft.Xna.Framework.Graphics.ClearOptions.DepthBuffer) != 0)
                flags |= DepthStencilClearFlags.Depth;
            if ((options & Microsoft.Xna.Framework.Graphics.ClearOptions.Stencil) != 0)
                flags |= DepthStencilClearFlags.Stencil;
            dx_dev_context.ClearDepthStencilView(current_depth_stencil_view, flags, depth, (byte)stencil);
        }

        int indexcount(PrimitiveType primitiveType, int primitiveCount)
        {
            // TODO: Add new version of this routine that accepts adjacency topology
            int indexcount = 0;
            switch (primitiveType)
            {
                case PrimitiveType.LineList:
                    indexcount = primitiveCount * 2;
                    break;
                case PrimitiveType.LineStrip:
                    indexcount = primitiveCount + 1;
                    break;
                case PrimitiveType.PointList:
                    indexcount = primitiveCount;
                    break;
                case PrimitiveType.TriangleFan:
                    throw new Exception("Sorry, DX10 does not support TriagleFan topology");
                case PrimitiveType.TriangleList:
                    indexcount = primitiveCount * 3;
                    break;
                case PrimitiveType.TriangleStrip:
                    indexcount = primitiveCount + 2;
                    break;
                case PrimitiveType.LineListWithAdjacency:
                    indexcount = primitiveCount * 4;
                    break;
                case PrimitiveType.LineStripWithAdjacency:
                    indexcount = (primitiveCount + 1) * 2;
                    break;
                case PrimitiveType.TriangleListWithAdjacency:
                    indexcount = primitiveCount * 6;
                    break;
                case PrimitiveType.TriangleStripWithAdjacency:
                    indexcount = (primitiveCount + 2) * 2;
                    break;

                //TODO: Check the indexcounts below. They may not be correct.
                case PrimitiveType.PatchListWith1ControlPoint: indexcount = 1 * primitiveCount; break;
                case PrimitiveType.PatchListWith2ControlPoints: indexcount = 2 * primitiveCount; break;
                case PrimitiveType.PatchListWith3ControlPoints: indexcount = 3 * primitiveCount; break;
                case PrimitiveType.PatchListWith4ControlPoints: indexcount = 4 * primitiveCount; break;
                case PrimitiveType.PatchListWith5ControlPoints: indexcount = 5 * primitiveCount; break;
                case PrimitiveType.PatchListWith6ControlPoints: indexcount = 6 * primitiveCount; break;
                case PrimitiveType.PatchListWith7ControlPoints: indexcount = 7 * primitiveCount; break;
                case PrimitiveType.PatchListWith8ControlPoints: indexcount = 8 * primitiveCount; break;
                case PrimitiveType.PatchListWith9ControlPoints: indexcount = 9 * primitiveCount; break;
                case PrimitiveType.PatchListWith10ControlPoints: indexcount = 10 * primitiveCount; break;

                case PrimitiveType.PatchListWith11ControlPoints: indexcount = 11 * primitiveCount; break;
                case PrimitiveType.PatchListWith12ControlPoints: indexcount = 12 * primitiveCount; break;
                case PrimitiveType.PatchListWith13ControlPoints: indexcount = 13 * primitiveCount; break;
                case PrimitiveType.PatchListWith14ControlPoints: indexcount = 14 * primitiveCount; break;
                case PrimitiveType.PatchListWith15ControlPoints: indexcount = 15 * primitiveCount; break;
                case PrimitiveType.PatchListWith16ControlPoints: indexcount = 16 * primitiveCount; break;
                case PrimitiveType.PatchListWith17ControlPoints: indexcount = 17 * primitiveCount; break;
                case PrimitiveType.PatchListWith18ControlPoints: indexcount = 18 * primitiveCount; break;
                case PrimitiveType.PatchListWith19ControlPoints: indexcount = 19 * primitiveCount; break;
                case PrimitiveType.PatchListWith20ControlPoints: indexcount = 20 * primitiveCount; break;

                case PrimitiveType.PatchListWith21ControlPoints: indexcount = 21 * primitiveCount; break;
                case PrimitiveType.PatchListWith22ControlPoints: indexcount = 22 * primitiveCount; break;
                case PrimitiveType.PatchListWith23ControlPoints: indexcount = 23 * primitiveCount; break;
                case PrimitiveType.PatchListWith24ControlPoints: indexcount = 24 * primitiveCount; break;
                case PrimitiveType.PatchListWith25ControlPoints: indexcount = 25 * primitiveCount; break;
                case PrimitiveType.PatchListWith26ControlPoints: indexcount = 26 * primitiveCount; break;
                case PrimitiveType.PatchListWith27ControlPoints: indexcount = 27 * primitiveCount; break;
                case PrimitiveType.PatchListWith28ControlPoints: indexcount = 28 * primitiveCount; break;
                case PrimitiveType.PatchListWith29ControlPoints: indexcount = 29 * primitiveCount; break;
                case PrimitiveType.PatchListWith30ControlPoints: indexcount = 30 * primitiveCount; break;

                case PrimitiveType.PatchListWith31ControlPoints: indexcount = 31 * primitiveCount; break;
                case PrimitiveType.PatchListWith32ControlPoints: indexcount = 32 * primitiveCount; break;
            }
            return indexcount;
        }

        SlimDX.Direct3D11.Buffer assignvertexbuffer<T>(T[] vertexData)
        {
            SlimDX.Direct3D11.Buffer vertex_buffer;
            BufferDescription bd;
            bd = new BufferDescription();

            bd.Usage = ResourceUsage.Default;
            int vertexelementsize = vdecl.GetVertexStrideSize();
            bd.SizeInBytes = vertexData.Length * vertexelementsize;
            bd.BindFlags = BindFlags.VertexBuffer;
            bd.CpuAccessFlags = CpuAccessFlags.None;
            bd.OptionFlags = ResourceOptionFlags.None;
            vertex_buffer = new SlimDX.Direct3D11.Buffer(dx_device, new DataStream(vertexData, true, false), bd);
            dx_dev_context.InputAssembler.SetVertexBuffers(0,
                                                      new VertexBufferBinding(vertex_buffer,
                                                                              vertexelementsize,
                                                                              0));
            return vertex_buffer;
        }

        public void DrawUserIndexedPrimitives<T>(PrimitiveType primitiveType,
                                                 T[] vertexData, int vertexOffset, int numVertices,
                                                 int[] indexData, int indexOffset,
                                                 int primitiveCount)
        {  // Version with 32 bit index values
            if (vdecl == null) throw new Exception("Vertex declaration not set on graphics device");
            SlimDX.Direct3D11.Buffer vertex_buffer, index_buffer;

            vertex_buffer = assignvertexbuffer<T>(vertexData);

            // Create and assign the index buffer
            BufferDescription bd;
            bd = new BufferDescription();
            bd.Usage = ResourceUsage.Default;
            bd.SizeInBytes = indexData.Length * 4;
            bd.BindFlags = BindFlags.IndexBuffer;
            bd.CpuAccessFlags = CpuAccessFlags.None;
            bd.OptionFlags = ResourceOptionFlags.None;
            index_buffer = new SlimDX.Direct3D11.Buffer(dx_device, new DataStream(indexData, true, false), bd);
            dx_dev_context.InputAssembler.SetIndexBuffer(index_buffer, SlimDX.DXGI.Format.R32_UInt, 0);

            dx_dev_context.InputAssembler.PrimitiveTopology = (EnumConversions.convert(primitiveType));
            dx_dev_context.DrawIndexed(indexcount(primitiveType, primitiveCount), indexOffset, vertexOffset);

            // Release buffers
            vertex_buffer.Dispose();
            index_buffer.Dispose();
        }

        public void DrawUserIndexedPrimitives<T>(PrimitiveType primitiveType,
                                                 T[] vertexData, int vertexOffset, int numVertices,
                                                 short[] indexData, int indexOffset,
                                                 int primitiveCount)
        {   // Version for 16 bit index values - this is just a copy of version above with two changes
            if (vdecl == null) throw new Exception("Vertex declaration not set on graphics device");
            SlimDX.Direct3D11.Buffer vertex_buffer, index_buffer;

            vertex_buffer = assignvertexbuffer<T>(vertexData);

            // Create and assign the index buffer
            BufferDescription bd;
            bd = new BufferDescription();
            bd.Usage = ResourceUsage.Default;
            bd.SizeInBytes = indexData.Length * 2;
            bd.BindFlags = BindFlags.IndexBuffer;
            bd.CpuAccessFlags = CpuAccessFlags.None;
            bd.OptionFlags = ResourceOptionFlags.None;
            index_buffer = new SlimDX.Direct3D11.Buffer(dx_device, new DataStream(indexData, true, false), bd);
            dx_dev_context.InputAssembler.SetIndexBuffer(index_buffer, SlimDX.DXGI.Format.R16_UInt, 0);

            dx_dev_context.InputAssembler.PrimitiveTopology = (EnumConversions.convert(primitiveType));
            dx_dev_context.DrawIndexed(indexcount(primitiveType, primitiveCount), indexOffset, vertexOffset);

            // Release buffers
            vertex_buffer.Dispose();
            index_buffer.Dispose();
        }

        public void DrawUserPrimitives<T>(PrimitiveType primitiveType,
                                          T[] vertexData, int vertexOffset, int primitiveCount)
        {
            if (vdecl == null) throw new Exception("Vertex declaration not set on graphics device");
            SlimDX.Direct3D11.Buffer vertex_buffer;

            vertex_buffer = assignvertexbuffer<T>(vertexData);
            dx_dev_context.InputAssembler.PrimitiveTopology = (EnumConversions.convert(primitiveType));
            dx_dev_context.Draw(indexcount(primitiveType, primitiveCount), vertexOffset);

            // Release buffer
            vertex_buffer.Dispose();
        }

        public void DrawIndexedPrimitives(PrimitiveType primitiveType,
                                          int baseVertex, int minVertexIndex, int numVertices,
                                          int startIndex,
                                          int primitiveCount)
        {
            if (vdecl == null) throw new Exception("Vertex declaration not set on graphics device");

            dx_dev_context.InputAssembler.PrimitiveTopology = (EnumConversions.convert(primitiveType));
            dx_dev_context.DrawIndexed(indexcount(primitiveType, primitiveCount), startIndex, baseVertex);
        }

        public void DrawPrimitives(PrimitiveType primitiveType,
                                   int startVertex, int primitiveCount)
        {
            if (vdecl == null) throw new Exception("Vertex declaration not set on graphics device");

            dx_dev_context.InputAssembler.PrimitiveTopology = (EnumConversions.convert(primitiveType));
            dx_dev_context.Draw(indexcount(primitiveType, primitiveCount), startVertex);
        }

        public void DrawAuto(PrimitiveType primitiveType)
        {
            if (vdecl == null) throw new Exception("Vertex declaration not set on graphics device");

            dx_dev_context.InputAssembler.PrimitiveTopology = (EnumConversions.convert(primitiveType));
            dx_dev_context.DrawAuto();
        }

        public void Dispatch(int x, int y, int z)
        {
            dx_dev_context.Dispatch(x, y, z);
        }

        internal void EndDraw()
        {
            swap_chain.Present(0, SlimDX.DXGI.PresentFlags.None);
        }

        public void Dispose()
        {
            // Cannot dispose swap chain when the display is full screen - so window first if necessary
            bool didfullscreen;
            SlimDX.DXGI.Output screendescription;
            swap_chain.GetFullScreenState(out didfullscreen, out screendescription);
            if (didfullscreen)
                swap_chain.SetFullScreenState(false, null);
            
            // Actual disposal
            renderstate.Dispose();
            backbuffer_render_target_view.Dispose();
            depth_stencil_view.Dispose();
            z_buffer.Dispose();
            swap_chain.Dispose();
            dx_device.Dispose();
        }
    }

    public sealed class VertexStream
    {
        GraphicsDevice device;
        int my_index;
        int offset;
        VertexBuffer vbuff;
        int stride;
        int frequency, indexfrequency, instancefrequency;

        public int OffsetInBytes { get { return offset; } }
        public VertexBuffer VertexBuffer { get { return vbuff; } }
        public int VertexStride { get { return stride; } }

        public void SetFrequency(int frequency) { this.frequency = frequency; }
        public void SetFrequencyOfIndexData(int frequency) { indexfrequency = frequency; }
        public void SetFrequencyOfInstanceData(int frequency) { instancefrequency = frequency; }

        internal VertexStream(GraphicsDevice dev, int s)
        {
            device = dev;
            my_index = s;
            offset = 0;
            vbuff = null;
            stride = 0;
            frequency = indexfrequency = instancefrequency = 0;
        }

        public void SetSource(VertexBuffer vb, int offsetInBytes, int vertexStride)
        {
            vbuff = vb;
            offset = offsetInBytes;
            stride = vertexStride;
            device.DX_Device_Context.InputAssembler.SetVertexBuffers(
                my_index, new SlimDX.Direct3D11.VertexBufferBinding((vbuff == null ? null : vbuff.DX_Buffer), stride, offset));
        }
    }

    public sealed class VertexStreamCollection
    {
        const int maxstreams = 10;
        VertexStream[] streams;

        public VertexStream this[int index] { get { return streams[index]; } }

        internal VertexStreamCollection(GraphicsDevice dev)
        {
            streams = new VertexStream[maxstreams];
            for (int s = 0; s < maxstreams; s++)
                streams[s] = new VertexStream(dev, s);
        }
    }
}

/*
/// <summary>
/// Performs primitive-based rendering, creates resources, handles system-level
/// variables, adjusts gamma ramp levels, and creates shaders.
/// </summary>
public class GraphicsDevice: IDisposable
{
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////// Constructors ////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////

  /// <summary>
  /// Creates an instance of this object.
  /// </summary>
  /// <param name="adapter">The display adapter.</param>
  /// <param name="graphicsProfile">The graphics profile.</param>
  /// <param name="presentationParameters">The presentation options.</param>
  public GraphicsDevice(GraphicsAdapter adapter, GraphicsProfile graphicsProfile, PresentationParameters presentationParameters)
  {
    throw new Exception("Not Yet Implemented");
  }
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////// Properties //////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////

  /// <summary>
  /// Gets a value that indicates whether the object is disposed.
  /// </summary>
  public bool IsDisposed { get { throw new Exception("NYI"); } }

  /// <summary>
  /// Gets or sets the rectangle used for scissor testing. By default, the size
  /// matches the render target size.
  /// </summary>
  public Rectangle ScissorRectangle { get { throw new Exception("NYI"); } set { } }

 * done

  /// <summary>
  /// Gets or sets a viewport identifying the portion of the render target to
  /// receive draw calls.  Reference page contains code sample.
  /// </summary>
  public Viewport Viewport { get { throw new Exception("NYI"); } set { } }

  /// <summary>
  /// Retrieves the display mode's spatial resolution, color resolution, and
  /// refresh frequency.  Reference page contains code sample.
  /// </summary>
  public DisplayMode DisplayMode { get { throw new Exception("NYI"); } }

  /// <summary>
  /// Retrieves the status of the device.
  /// </summary>
  public GraphicsDeviceStatus GraphicsDeviceStatus { get { throw new Exception("NYI"); } }

  /// <summary>
  /// Gets the graphics profile. The default value is GraphicsProfile.Reach.
  /// </summary>
  public GraphicsProfile GraphicsProfile { get { throw new Exception("NYI"); } }

  /// <summary>
  /// Gets the graphics adapter.
  /// </summary>
  public GraphicsAdapter Adapter { get { throw new Exception("NYI"); } }

  /// <summary>
  /// Gets the presentation parameters associated with this graphics device.
  /// </summary>
  public PresentationParameters PresentationParameters { get { throw new Exception("NYI"); } }

  /// <summary>
  /// Gets or sets rasterizer state. The default value is
  /// RasterizerState.CullCounterClockwise.
  /// </summary>
  public RasterizerState RasterizerState { get { throw new Exception("NYI"); } set { } }

  /// <summary>
  /// Gets or sets a reference value for stencil testing. The default value is
  /// zero.
  /// </summary>
  public int ReferenceStencil { get { throw new Exception("NYI"); } set { } }

  /// <summary>
  /// Gets or sets a system-defined instance of a depth-stencil state object.
  /// The default value is DepthStencilState.Default.
  /// </summary>
  public DepthStencilState DepthStencilState { get { throw new Exception("NYI"); } set { } }

  /// <summary>
  /// Gets or sets a bitmask controlling modification of the samples in a
  /// multisample render target. The default value is -1 (0xffffffff).
  /// </summary>
  public int MultiSampleMask { get { throw new Exception("NYI"); } set { } }

  /// <summary>
  /// Gets or sets the color used for a constant-blend factor during alpha
  /// blending. The default value is Color.White.
  /// </summary>
  public Color BlendFactor { get { throw new Exception("NYI"); } set { } }

  /// <summary>
  /// Gets or sets a system-defined instance of a blend state object
  /// initialized for alpha blending. The default value is BlendState.Opaque.
  /// </summary>
  public BlendState BlendState { get { throw new Exception("NYI"); } set { } }

  /// <summary>
  /// Gets the collection of vertex textures that support texture lookup in the
  /// vertex shader using the texldl statement. The vertex engine contains four
  /// texture sampler stages.
  /// </summary>
  public TextureCollection VertexTextures { get { throw new Exception("NYI"); } }

  /// <summary>
  /// Returns the collection of textures that have been assigned to the texture
  /// stages of the device.  Reference page contains code sample.
  /// </summary>
  public TextureCollection Textures { get { throw new Exception("NYI"); } }

  /// <summary>
  /// Gets the collection of vertex sampler states.
  /// </summary>
  public SamplerStateCollection VertexSamplerStates { get { throw new Exception("NYI"); } }

  /// <summary>
  /// Retrieves a collection of SamplerState objects for the current
  /// GraphicsDevice.
  /// </summary>
  public SamplerStateCollection SamplerStates { get { throw new Exception("NYI"); } }

  //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////// Methods /////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////

  /// <summary>
  /// Gets the contents of the back buffer.
  /// </summary>
  /// <param name="data">Array of data.</param>
  /// <param name="startIndex">The first element to use.</param>
  /// <param name="elementCount">The number of elements to use.</param>
  public void GetBackBufferData<T>(T[] data, int startIndex, int elementCount)
  {
    throw new Exception("Not Yet Implemented");
  }

  /// <summary>
  /// Gets the contents of the back buffer.
  /// </summary>
  /// <param name="data">Array of data.</param>
  public void GetBackBufferData<T>(T[] data)
  {
    throw new Exception("Not Yet Implemented");
  }

  public VertexBufferBinding[] GetVertexBuffers()
  {
    throw new Exception("Not Yet Implemented");
  }

  /// <summary>
  /// Sets or binds a vertex buffer to the device.
  /// </summary>
  /// <param name="vertexBuffer">A vertex buffer.</param>
  /// <param name="vertexOffset">The offset (in vertices) from the beginning of
  /// the buffer.</param>
  public void SetVertexBuffer(VertexBuffer vertexBuffer, int vertexOffset)
  {
    throw new Exception("Not Yet Implemented");
  }

 * done
  /// <summary>
  /// Sets or binds a vertex buffer to the device.
  /// </summary>
  /// <param name="vertexBuffer">A vertex buffer.</param>
  public void SetVertexBuffer(VertexBuffer vertexBuffer)
  {
    throw new Exception("Not Yet Implemented");
  }

  /// <summary>
  /// Sets the vertex buffers.
  /// </summary>
  /// <param name="vertexBuffers">[ParamArrayAttribute] An array of vertex
  /// buffers.</param>
  public void SetVertexBuffers(VertexBufferBinding[] vertexBuffers)
  {
    throw new Exception("Not Yet Implemented");
  }

  public void add_Disposing(EventHandler<EventArgs> value)
  {
    throw new Exception("Not Yet Implemented");
  }

  public void remove_Disposing(EventHandler<EventArgs> value)
  {
    throw new Exception("Not Yet Implemented");
  }

  protected void raise_Disposing(Object value0, EventArgs value1)
  {
    throw new Exception("Not Yet Implemented");
  }

  /// <summary>
  /// Immediately releases the unmanaged resources used by this object.
  /// </summary>
  /// <param name="disposing">[MarshalAsAttribute(U1)] true to release both
  /// managed and unmanaged resources; false to release only unmanaged
  /// resources.</param>
  protected virtual void Dispose(bool value)
  {
    throw new Exception("Not Yet Implemented");
  }

  public final virtual void Dispose()
  {
    throw new Exception("Not Yet Implemented");
  }

  protected virtual void Finalize()
  {
    throw new Exception("Not Yet Implemented");
  }

  /// <summary>
  /// Specifies the window target for a presentation and presents the display
  /// with the contents of the next buffer in the sequence of back buffers
  /// owned by the GraphicsDevice.
  /// </summary>
  /// <param name="sourceRectangle">The source rectangle. If null, the entire
  /// source surface is presented. If the rectangle exceeds the source surface,
  /// the rectangle is clipped to the source surface.</param>
  /// <param name="destinationRectangle">The destination rectangle, in window
  /// client coordinates. If null, the entire client area is filled. If the
  /// rectangle exceeds the destination client area, the rectangle is clipped
  /// to the destination client area.</param>
  /// <param name="overrideWindowHandle">Destination window containing the
  /// client area that is the target for this presentation. If not specified,
  /// this is DeviceWindowHandle.</param>
  public void Present(Nullable<Rectangle> sourceRectangle, Nullable<Rectangle> destinationRectangle, **IntPtr** overrideWindowHandle)
  {
    throw new Exception("Not Yet Implemented");
  }

  public void Present()
  {
    throw new Exception("Not Yet Implemented");
  }

  public void add_DeviceResetting(EventHandler<EventArgs> value)
  {
    throw new Exception("Not Yet Implemented");
  }

  public void remove_DeviceResetting(EventHandler<EventArgs> value)
  {
    throw new Exception("Not Yet Implemented");
  }

  protected void raise_DeviceResetting(Object value0, EventArgs value1)
  {
    throw new Exception("Not Yet Implemented");
  }

  public void add_DeviceReset(EventHandler<EventArgs> value)
  {
    throw new Exception("Not Yet Implemented");
  }

  public void remove_DeviceReset(EventHandler<EventArgs> value)
  {
    throw new Exception("Not Yet Implemented");
  }

  protected void raise_DeviceReset(Object value0, EventArgs value1)
  {
    throw new Exception("Not Yet Implemented");
  }

  public void add_DeviceLost(EventHandler<EventArgs> value)
  {
    throw new Exception("Not Yet Implemented");
  }

  public void remove_DeviceLost(EventHandler<EventArgs> value)
  {
    throw new Exception("Not Yet Implemented");
  }

  protected void raise_DeviceLost(Object value0, EventArgs value1)
  {
    throw new Exception("Not Yet Implemented");
  }

  public void add_ResourceCreated(EventHandler<ResourceCreatedEventArgs> value)
  {
    throw new Exception("Not Yet Implemented");
  }

  public void remove_ResourceCreated(EventHandler<ResourceCreatedEventArgs> value)
  {
    throw new Exception("Not Yet Implemented");
  }

  protected void raise_ResourceCreated(Object value0, ResourceCreatedEventArgs value1)
  {
    throw new Exception("Not Yet Implemented");
  }

  public void add_ResourceDestroyed(EventHandler<ResourceDestroyedEventArgs> value)
  {
    throw new Exception("Not Yet Implemented");
  }

  public void remove_ResourceDestroyed(EventHandler<ResourceDestroyedEventArgs> value)
  {
    throw new Exception("Not Yet Implemented");
  }

  protected void raise_ResourceDestroyed(Object value0, ResourceDestroyedEventArgs value1)
  {
    throw new Exception("Not Yet Implemented");
  }

  public void Reset()
  {
    throw new Exception("Not Yet Implemented");
  }

  /// <summary>
  /// Resets the current GraphicsDevice with the specified
  /// PresentationParameters.
  /// </summary>
  /// <param name="presentationParameters">Describes the new presentation
  /// parameters. This value cannot be null.</param>
  public void Reset(PresentationParameters presentationParameters)
  {
    throw new Exception("Not Yet Implemented");
  }

  /// <summary>
  /// Resets the specified Reset with the specified presentation parameters.
  /// </summary>
  /// <param name="presentationParameters">Describes the new presentation
  /// parameters. This value cannot be null.</param>
  /// <param name="graphicsAdapter">The graphics device being reset.</param>
  public void Reset(PresentationParameters presentationParameters, GraphicsAdapter graphicsAdapter)
  {
    throw new Exception("Not Yet Implemented");
  }

  /// <summary>
  /// Renders a sequence of non-indexed geometric primitives of the specified
  /// type from the current set of data input streams.
  /// </summary>
  /// <param name="primitiveType">Describes the type of primitive to render.
  /// </param>
  /// <param name="startVertex">Index of the first vertex to load. Beginning at
  /// startVertex, the correct number of vertices is read out of the vertex
  /// buffer.</param>
  /// <param name="primitiveCount">Number of primitives to render. The
  /// primitiveCount is the number of primitives as determined by the primitive
  /// type. If it is a line list, each primitive has two vertices. If it is a
  /// triangle list, each primitive has three vertices.</param>
  public void DrawPrimitives(PrimitiveType primitiveType, int startVertex, int primitiveCount)
  {
    throw new Exception("Not Yet Implemented");
  }

  /// <summary>
  /// Renders the specified geometric primitive, based on indexing into an
  /// array of vertices.
  /// </summary>
  /// <param name="primitiveType">Describes the type of primitive to render.
  /// PrimitiveType.PointList is not supported with this method.</param>
  /// <param name="baseVertex">Offset to add to each vertex index in the index
  /// buffer.</param>
  /// <param name="minVertexIndex">Minimum vertex index for vertices used
  /// during the call. The minVertexIndex parameter and all of the indices in
  /// the index stream are relative to the baseVertex parameter.</param>
  /// <param name="numVertices">Number of vertices used during the call. The
  /// first vertex is located at index: baseVertex + minVertexIndex.</param>
  /// <param name="startIndex">Location in the index array at which to start
  /// reading vertices.</param>
  /// <param name="primitiveCount">Number of primitives to render. The number
  /// of vertices used is a function of primitiveCount and primitiveType.
  /// </param>
  public void DrawIndexedPrimitives(PrimitiveType primitiveType, int baseVertex, int minVertexIndex, int numVertices, int startIndex, int primitiveCount)
  {
    throw new Exception("Not Yet Implemented");
  }

  /// <summary>
  /// Draws a series of instanced models.
  /// </summary>
  /// <param name="primitiveType">The primitive type.</param>
  /// <param name="baseVertex">Offset to add to each vertex index in the index
  /// buffer.</param>
  /// <param name="minVertexIndex">Minimum vertex index for vertices used
  /// during the call. The minVertexIndex parameter and all of the indices in
  /// the index stream are relative to the baseVertex parameter.</param>
  /// <param name="numVertices">Number of vertices used during the call. The
  /// first vertex is located at index: baseVertex + minVertexIndex.</param>
  /// <param name="startIndex">Location in the index array at which to start
  /// reading vertices.</param>
  /// <param name="primitiveCount">Number of primitives to render. The number
  /// of vertices used is a function of primitiveCount and primitiveType.
  /// </param>
  /// <param name="instanceCount">Number of primitives to render.</param>
  public void DrawInstancedPrimitives(PrimitiveType primitiveType, int baseVertex, int minVertexIndex, int numVertices, int startIndex, int primitiveCount, int instanceCount)
  {
    throw new Exception("Not Yet Implemented");
  }

  /// <summary>
  /// Renders indexed primitives from a 32-bit index buffer and other related
  /// input parameters.
  /// </summary>
  /// <param name="primitiveType">The primitive type.</param>
  /// <param name="vertexData">The vertex data.</param>
  /// <param name="vertexOffset">Offset (in vertices) from the beginning of the
  /// vertex buffer to the first vertex to draw.</param>
  /// <param name="numVertices">Number of vertices to draw.</param>
  /// <param name="indexData">The index data.</param>
  /// <param name="indexOffset">Offset (in indices) from the beginning of the
  /// index buffer to the first index to use.</param>
  /// <param name="primitiveCount">Number of primitives to render.</param>
  public void DrawUserIndexedPrimitives<T>(PrimitiveType primitiveType, T[] vertexData, int vertexOffset, int numVertices, int[] indexData, int indexOffset, int primitiveCount) where T : IVertexType
  {
    throw new Exception("Not Yet Implemented");
  }

  /// <summary>
  /// Renders indexed primitives from a 16-bit index buffer and other related
  /// input parameters.
  /// </summary>
  /// <param name="primitiveType">The primitive type.</param>
  /// <param name="vertexData">The vertex data.</param>
  /// <param name="vertexOffset">Offset (in vertices) from the beginning of the
  /// vertex buffer to the first vertex to draw.</param>
  /// <param name="numVertices">Number of vertices to draw.</param>
  /// <param name="indexData">The index data.</param>
  /// <param name="indexOffset">Offset (in indices) from the beginning of the
  /// index buffer to the first index to use.</param>
  /// <param name="primitiveCount">Number of primitives to render.</param>
  public void DrawUserIndexedPrimitives<T>(PrimitiveType primitiveType, T[] vertexData, int vertexOffset, int numVertices, **Int16**[] indexData, int indexOffset, int primitiveCount) where T : IVertexType
  {
    throw new Exception("Not Yet Implemented");
  }

  /// <summary>
  /// Renders indexed primitives from a 32-bit index buffer, a vertex
  /// declaration, and other related input parameters.
  /// </summary>
  /// <param name="primitiveType">The primitive type.</param>
  /// <param name="vertexData">The vertex data.</param>
  /// <param name="vertexOffset">Offset (in vertices) from the beginning of the
  /// vertex buffer to the first vertex to draw.</param>
  /// <param name="numVertices">Number of vertices to draw.</param>
  /// <param name="indexData">The index data.</param>
  /// <param name="indexOffset">Offset (in indices) from the beginning of the
  /// index buffer to the first index to use.</param>
  /// <param name="primitiveCount">Number of primitives to render.</param>
  /// <param name="vertexDeclaration">The vertex declaration.</param>
  public void DrawUserIndexedPrimitives<T>(PrimitiveType primitiveType, T[] vertexData, int vertexOffset, int numVertices, int[] indexData, int indexOffset, int primitiveCount, VertexDeclaration vertexDeclaration)
  {
    throw new Exception("Not Yet Implemented");
  }

  /// <summary>
  /// Renders indexed primitives from a 16-bit index buffer, a vertex
  /// declaration, and other related input parameters.
  /// </summary>
  /// <param name="primitiveType">The primitive type.</param>
  /// <param name="vertexData">The vertex data.</param>
  /// <param name="vertexOffset">Offset (in vertices) from the beginning of the
  /// vertex buffer to the first vertex to draw.</param>
  /// <param name="numVertices">Number of vertices to draw.</param>
  /// <param name="indexData">The index data.</param>
  /// <param name="indexOffset">Offset (in indices) from the beginning of the
  /// index buffer to the first index to use.</param>
  /// <param name="primitiveCount">Number of primitives to render.</param>
  /// <param name="vertexDeclaration">The vertex declaration.</param>
  public void DrawUserIndexedPrimitives<T>(PrimitiveType primitiveType, T[] vertexData, int vertexOffset, int numVertices, **Int16**[] indexData, int indexOffset, int primitiveCount, VertexDeclaration vertexDeclaration)
  {
    throw new Exception("Not Yet Implemented");
  }

  /// <summary>
  /// Draws primitives.
  /// </summary>
  /// <param name="primitiveType">Describes the type of primitive to render.
  /// </param>
  /// <param name="vertexData">The vertex data.</param>
  /// <param name="vertexOffset">Offset (in vertices) from the beginning of the
  /// buffer to start reading data.</param>
  /// <param name="primitiveCount">Number of primitives to render.</param>
  public void DrawUserPrimitives<T>(PrimitiveType primitiveType, T[] vertexData, int vertexOffset, int primitiveCount) where T : IVertexType
  {
    throw new Exception("Not Yet Implemented");
  }

  /// <summary>
  /// Draws primitives.
  /// </summary>
  /// <param name="primitiveType">Describes the type of primitive to render.
  /// </param>
  /// <param name="vertexData">The vertex data.</param>
  /// <param name="vertexOffset">Offset (in vertices) from the beginning of the
  /// buffer to start reading data.</param>
  /// <param name="primitiveCount">Number of primitives to render.</param>
  /// <param name="vertexDeclaration">The vertex declaration, which defines
  /// per-vertex data.</param>
  public void DrawUserPrimitives<T>(PrimitiveType primitiveType, T[] vertexData, int vertexOffset, int primitiveCount, VertexDeclaration vertexDeclaration)
  {
    throw new Exception("Not Yet Implemented");
  }

  /// <summary>
  /// Clears resource buffers.
  /// </summary>
  /// <param name="options">Options for clearing a buffer.</param>
  /// <param name="color">Set this four-component color value in the buffer.
  /// </param>
  /// <param name="depth">Set this depth value in the buffer.</param>
  /// <param name="stencil">Set this stencil value in the buffer.</param>
  public void Clear(ClearOptions options, Vector4 color, float depth, int stencil)
  {
    throw new Exception("Not Yet Implemented");
  }

  /// <summary>
  /// Clears resource buffers.
  /// </summary>
  /// <param name="options">Options for clearing a buffer.</param>
  /// <param name="color">Set this color value in the buffer.</param>
  /// <param name="depth">Set this depth value in the buffer.</param>
  /// <param name="stencil">Set this stencil value in the buffer.</param>
  public void Clear(ClearOptions options, Color color, float depth, int stencil)
  {
    throw new Exception("Not Yet Implemented");
  }

  /// <summary>
  /// Clears resource buffers.
  /// </summary>
  /// <param name="color">Set this color value in all buffers.</param>
  public void Clear(Color color)
  {
    throw new Exception("Not Yet Implemented");
  }

  /// <summary>
  /// Sets an array of render targets.
  /// </summary>
  /// <param name="renderTargets">[ParamArrayAttribute] An array of render
  /// targets.</param>
  public void SetRenderTargets(RenderTargetBinding[] renderTargets)
  {
    throw new Exception("Not Yet Implemented");
  }

  /// <summary>
  /// Sets a new render target for this GraphicsDevice.
  /// </summary>
  /// <param name="renderTarget">A new render target for the device, or null to
  /// set the device render target to the back buffer of the device.</param>
  /// <param name="cubeMapFace">The cube map face type.</param>
  public void SetRenderTarget(RenderTargetCube renderTarget, CubeMapFace cubeMapFace)
  {
    throw new Exception("Not Yet Implemented");
  }

  /// <summary>
  /// Sets a new render target for this GraphicsDevice.
  /// </summary>
  /// <param name="renderTarget">A new render target for the device, or null to
  /// set the device render target to the back buffer of the device.</param>
  public void SetRenderTarget(RenderTarget2D renderTarget)
  {
    throw new Exception("Not Yet Implemented");
  }

  public RenderTargetBinding[] GetRenderTargets()
  {
    throw new Exception("Not Yet Implemented");
  }

  /// <summary>
  /// Gets the contents of the back buffer.
  /// </summary>
  /// <param name="rect">The section of the back buffer to copy. null indicates
  /// the data will be copied from the entire back buffer.</param>
  /// <param name="data">Array of data.</param>
  /// <param name="startIndex">The first element to use.</param>
  /// <param name="elementCount">The number of elements to use.</param>
  public void GetBackBufferData<T>(Nullable<Rectangle> rect, T[] data, int startIndex, int elementCount)
  {
    throw new Exception("Not Yet Implemented");
  }
}
*/